#include "VigilatorLocal.h"

namespace varayoc
{
namespace vigilance
{
namespace runnable
{

VigilatorLocal::VigilatorLocal()
{
   m_running   = False;
   m_frequency.empty();

   fr = 0.1; // Donde se define este valor?

   // Creacion unica de Timers al ejecutarse el sub-sistema
   m_verify_class_aereo = varayoc::vigilance::util::Timer::create();
   m_verify_class_super = varayoc::vigilance::util::Timer::create();
}

/* 1 */
Void  VigilatorLocal::readCollectionTrack()
{
   SimulatedTrackCollection         entities;
   ddswrapper::DataInfoCollection   topicDataInfoCollection;
   m_streader->read(topicDataInfoCollection, entities);

   for (UInt i = 0; i < entities.size(); i++)
   {
      processingTrack(topicDataInfoCollection[i], entities[i]);
   }
}

Void  VigilatorLocal::initialize()
{
   m_allSimTrackHash.clear();
   m_nearSimTrackHash.clear();

   m_relativeCircularHash.clear();
   m_fixedCircularHash.clear();
   m_relativePolylineHash.clear();
   m_fixedPolylineHash.clear();

   m_currentVigilanceMap.clear();

   m_DisposeFigureTopics.clear();
   m_DisposeTrackTopics.clear();

   m_LimLatitude.clear();
   m_LimLongitude.clear();

   m_ClassAereo   = False;
   m_ClassSuper   = False;
}

Void  VigilatorLocal::readSecuritySectorCollection()
{
   // test
   cout << "|---------------------------------------------------------------------------" << endl;

   VigilanceAlarmCollection         entitiesVA;
   ddswrapper::DataInfoCollection   topicDataInfoCollectionVA;
   m_vareader->read(topicDataInfoCollectionVA, entitiesVA);
   for (UInt i = 0; i < entitiesVA.size(); i++)
   {
      VigilanceAlarm_ptr      c = entitiesVA[i];
      cout << "getVigilanceAlarmID     : " << c->getVigilanceAlarmID().c_str() << endl;
   }

   TrackVigilanceAlarmCollection    entitiesTVA;
   ddswrapper::DataInfoCollection   topicDataInfoCollectionTVA;
   m_tvareader->read(topicDataInfoCollectionTVA, entitiesTVA);
   for (UInt i = 0; i < entitiesTVA.size(); i++)
   {
      TrackVigilanceAlarm_ptr c = entitiesTVA[i];
      cout << "getTrackVigilanceAlarmID: " << c->getTrackVigilanceAlarmID().c_str() << endl;
   }
   cout << "---------------------------------------------------------------------------|" << endl;
}

/* 2 */
Void  VigilatorLocal::readFilteredTrackCollection()
{
   SimulatedTrackKinematicCollection   entitiesST;
   ddswrapper::DataInfoCollection      topicDataInfoCollectionST;
   ddswrapper::Query_ptr               query;

   // Obtencion de los limites de latitud y longitud para la busqueda de tracks simulados
   Vector<String>::Type m_LatLonLimites   = detectionAlgorithm.calculateUniversalLatLon(m_LimLatitude, m_LimLongitude, fr);

   if (!m_LatLonLimites.empty())
   {
      query = m_stk_reader->createQuery("CurrentLatitude <= %0 and CurrentLongitude <= %1 and %2 <= CurrentLatitude and %3 <= CurrentLongitude", m_LatLonLimites);
      m_stk_reader->readQuery(topicDataInfoCollectionST, entitiesST, query);
   }
   else
   {
      m_stk_reader->read(topicDataInfoCollectionST, entitiesST);
   }

   Bool  bClassification;

   // tracks simulados  - filtrados x clasificacion
   for (UInt i = 0; i < entitiesST.size(); i++)
   {
      pair<string, UInt>   value;
      value.first   = entitiesST[i]->getSimulatedTrackId().c_str();
      value.second  = TrackTopic_SIMULATED_TRACK;

      bClassification   = False;
      if (!isDisposedState(topicDataInfoCollectionST[i]))
      {
         // Se puede filtrar por clase, y se necesita un timer x cada clase de track
         // clasificacion de tracks simulados: desconocido o enemigo
         bClassification = (entitiesST[i]->getSimulatedTrackClassification() == simulation::TrackClassification_Desconocido) ||
                           (entitiesST[i]->getSimulatedTrackClassification() == simulation::TrackClassification_Enemigo);

         if (bClassification)
         {
            m_allSimTrackHash[entitiesST[i]->getSimulatedTrackId()] = entitiesST[i];
         }
         else
         {
            // no es enemigo o no es desconocido, pero puede ser amigo o neutral
            // verificar si esta en la tabla mas reciente de tracks detectados
            if (isThereTrackOId(value))
            {
               // el track cambio de clasificacion, pero no se encuentra en estado dispose
               // agregamos a la lista de los tracks con estado dispose
               m_DisposeTrackTopics.push_back(value);
            }
            else
            {
               // track sin interes
            }
         }
      }
      else
      {
         if (isThereTrackOId(value))
         {
            // aqui se guarda el track en estado dispose que fue un track detectado en algun sector de seguridad
            // se agrega a la lista de topicos track con estado dispose
            m_DisposeTrackTopics.push_back(value);
         }
         else
         {
            // no fue un track detectado, pero tiene estado dispose
         }
      }
   }

   ///////////////////////////////////////////
   // Test
   HashMap<OID, SimulatedTrackKinematic_ptr>::Type::iterator it;
   cout << "|===========================================================================" << endl;
   for (it = m_allSimTrackHash.begin(); it != m_allSimTrackHash.end(); it++)
   {
//      cout << "first : " << (*it).first << endl;
      cout << "m_allSimTrackHash    : " << (*it).second->getName() << endl;
   }

   list<pair<string, UInt> >::iterator jt;//
   for (jt = m_DisposeTrackTopics.begin(); jt != m_DisposeTrackTopics.end(); jt++)
   {
      cout << "m_DisposeTrackTopics : " << (*jt).first << endl;
   }
   cout << "===========================================================================|" << endl;
   ///////////////////////////////////////////

   // tracks reales     - todas las clases
/*
   for (UInt i = 0; i < entities.size(); i++)
   {
      m_allTrackHash[entities[i]->getTrackId()] = entities[i];
   }
*/

}

/* 1 */
Void  VigilatorLocal::readFilteredFigureCollection()
{
   RelativeCircularFigureKinematicCollection entitiesRCF;
   ddswrapper::DataInfoCollection            topicDataInfoCollectionRCF;
   m_rcfkreader->read(topicDataInfoCollectionRCF, entitiesRCF);

   FixedCircularFigureCollection             entitiesFCF;
   ddswrapper::DataInfoCollection            topicDataInfoCollectionFCF;
   m_fcfreader->read(topicDataInfoCollectionFCF, entitiesFCF);

   RelativePolylineFigureKinematicCollection entitiesRPF;
   ddswrapper::DataInfoCollection            topicDataInfoCollectionPF;
   m_rpfkreader->read(topicDataInfoCollectionPF, entitiesRPF);

   FixedPolylineFigureCollection             entitiesFPF;
   ddswrapper::DataInfoCollection            topicDataInfoCollectionFPF;
   m_fpfreader->read(topicDataInfoCollectionFPF, entitiesFPF);

   // figuras circular relativa - todos los tipos posibles "cerrados"

   for (UInt i = 0; i < entitiesRCF.size(); i++)
   {
      if (!isDisposedState(topicDataInfoCollectionRCF[i]))
      {
         if (entitiesRCF[i]->getSectorTypeValue() == navigationaid::SectorType_SECURITY_SECTOR)
         {
            m_relativeCircularHash[entitiesRCF[i]->getRelativeCircularFigureId()] = entitiesRCF[i];
            // limites
            m_LimLatitude.push_back(entitiesRCF[i]->getMinLatitude());
            m_LimLatitude.push_back(entitiesRCF[i]->getMaxLatitude());
            m_LimLongitude.push_back(entitiesRCF[i]->getMinLongitude());
            m_LimLongitude.push_back(entitiesRCF[i]->getMaxLongitude());
         }
         else
         {
            // No tiene estado dispose & No es sector de seguridad, no se agrega a m_relativeCircularHash
         }
      }
      else
      {
         // Existe este topico en la ultima lista m_earlierVigilanceMap escrita?
         pair<string, UInt>   key;
         key.first   = entitiesRCF[i]->getRelativeCircularFigureId().c_str();
         key.second  = SecuritySectorFigureTopic_RELATIVE_CIRCULAR_FIGURE;
         multimap<pair<string, UInt>, pair<string, UInt> >::iterator   it;
         it = m_earlierVigilanceMap.find(key);
         if (it != m_earlierVigilanceMap.end())
         {
            // aqui se guarda el topico en estado dispose que fue sector de seguridad
            // se agrega a la lista de topicos con estado dispose
            m_DisposeFigureTopics.push_back(key);
         }
         else
         {
            // no es sector de seguridad
         }
      }
   }

   // figuras circular fijas - todos los tipos posibles "cerrados"

   for (UInt i = 0; i < entitiesFCF.size(); i++)
   {
      // disposed?
      if (!isDisposedState(topicDataInfoCollectionFCF[i]))
      {
         // tipo de sector?
         if (entitiesFCF[i]->getSectorTypeValue() == navigationaid::SectorType_SECURITY_SECTOR)
         {
            // no es dipose y es sector de seguridad, se agrega a m_fixedCircularHash
            m_fixedCircularHash[entitiesFCF[i]->getFixedCircularFigureId()] = entitiesFCF[i];
            // limites
            m_LimLatitude.push_back(entitiesFCF[i]->getMinLatitude());
            m_LimLatitude.push_back(entitiesFCF[i]->getMaxLatitude());
            m_LimLongitude.push_back(entitiesFCF[i]->getMinLongitude());
            m_LimLongitude.push_back(entitiesFCF[i]->getMaxLongitude());
         }
         else
         {
            // no es dispose y no es sector de seguridad
         }
      }
      else
      {
         // topic dispose
         pair<string, UInt>   key;
         key.first   = entitiesFCF[i]->getFixedCircularFigureId().c_str();
         key.second  = SecuritySectorFigureTopic_FIXED_CIRCULAR_FIGURE;
         multimap<pair<string, UInt>, pair<string, UInt> >::iterator it;
         it = m_earlierVigilanceMap.find(key);
         // esta este topico en la ultima lista?
         if (it != m_earlierVigilanceMap.end())
         {
            m_DisposeFigureTopics.push_back(key);
         }
         else
         {
            // no esta en la lista anterior => no fue sector de seguridad
         }
      }
   }

   // figuras polyline relativas - todos los tipos posibles "cerrados"
   for (UInt i = 0; i < entitiesRPF.size(); i++)
   {
      if (!isDisposedState(topicDataInfoCollectionPF[i]))
      {
         if (entitiesRPF[i]->getSectorTypeValue() == navigationaid::SectorType_SECURITY_SECTOR)
         {
            m_relativePolylineHash[entitiesRPF[i]->getRelativePolylineFigureId()] = entitiesRPF[i];
            // limites
            m_LimLatitude.push_back(entitiesRPF[i]->getMinLatitude());
            m_LimLatitude.push_back(entitiesRPF[i]->getMaxLatitude());
            m_LimLongitude.push_back(entitiesRPF[i]->getMinLongitude());
            m_LimLongitude.push_back(entitiesRPF[i]->getMaxLongitude());
         }
         else
         {
            // No tiene estado dispose & No es sector de seguridad, no se agrega a m_relativePolylineHash
         }
      }
      else
      {
         // Existe este topico en la ultima lista m_earlierVigilanceMap escrita?
         // multimap<std::pair<string, UInt>, string> m_recentVigilanceMaps
         pair<string, UInt>   key;
         key.first   = entitiesRPF[i]->getRelativePolylineFigureId().c_str();
         key.second  = SecuritySectorFigureTopic_RELATIVE_POLYLINE_FIGURE;
         multimap<pair<string, UInt>, pair<string, UInt> >::iterator   it;
         it = m_earlierVigilanceMap.find(key);
         if (it != m_earlierVigilanceMap.end())
         {
            // aqui se guarda el topico en estado dispose que fue sector de seguridad
            // se agrega a la lista de topicos con estado dispose
            m_DisposeFigureTopics.push_back(key);
         }
         else
         {
            // no es sector de seguridad
         }
      }
   }

   // figuras polyline fijas - todos los tipos posibles "cerrados"
   for (UInt i = 0; i < entitiesFPF.size(); i++)
   {
      if (!isDisposedState(topicDataInfoCollectionFPF[i]))
      {
         if (entitiesFPF[i]->getSectorTypeValue() == navigationaid::SectorType_SECURITY_SECTOR)
         {
            m_fixedPolylineHash[entitiesFPF[i]->getFixedPolylineFigureId()] = entitiesFPF[i];
            // limites
            m_LimLatitude.push_back(entitiesFPF[i]->getMinLatitude());
            m_LimLatitude.push_back(entitiesFPF[i]->getMaxLatitude());
            m_LimLongitude.push_back(entitiesFPF[i]->getMinLongitude());
            m_LimLongitude.push_back(entitiesFPF[i]->getMaxLongitude());
         }
         else
         {
            // No tiene estado dispose & No es sector de seguridad, no se agrega a m_fixedPolylineHash
         }
      }
      else
      {
         // Existe este topico en la ultima lista m_earlierVigilanceMap escrita?
         pair<string, UInt>   key;
         key.first   = entitiesFPF[i]->getFixedPolylineFigureId().c_str();
         key.second  = SecuritySectorFigureTopic_FIXED_POLYLINE_FIGURE;
         multimap<pair<string, UInt>, pair<string, UInt> >::iterator   it;
         it = m_earlierVigilanceMap.find(key);
         if (it != m_earlierVigilanceMap.end())
         {
            // aqui se guarda el topico en estado dispose que fue sector de seguridad
            // se agrega a la lista de topicos con estado dispose
            m_DisposeFigureTopics.push_back(key);
         }
         else
         {
            // no es sector de seguridad
         }
      }
   }

   ///////////////////////////////////////////
   // Test
   cout << "|---------------------------------------------------------------------------" << endl;
   HashMap<OID, RelativeCircularFigureKinematic_ptr>::Type::iterator it;
   for (it = m_relativeCircularHash.begin(); it != m_relativeCircularHash.end(); it++)
   {
      cout << "m_relativeCircularHash  : " << (*it).second->getName() << endl;
   }
   HashMap<OID, FixedCircularFigure_ptr>::Type::iterator jt;
   for (jt = m_fixedCircularHash.begin(); jt != m_fixedCircularHash.end(); jt++)
   {
      cout << "m_fixedCircularHash     : " << (*jt).second->getName() << endl;
   }
   HashMap<OID, RelativePolylineFigureKinematic_ptr>::Type::iterator kt;
   for (kt = m_relativePolylineHash.begin(); kt != m_relativePolylineHash.end(); kt++)
   {
      cout << "m_relativePolylineHash  : " << (*kt).second->getName() << endl;
   }
   HashMap<OID, FixedPolylineFigure_ptr>::Type::iterator lt;
   for (lt = m_fixedPolylineHash.begin(); lt != m_fixedPolylineHash.end(); lt++)
   {
      cout << "m_fixedPolylineHash     : " << (*lt).second->getName() << endl;
   }
   cout << "---------------------------------------------------------------------------|" << endl;
   ///////////////////////////////////////////
}

Void  VigilatorLocal::deleteTrackVigilanceAlarm(OID TrackVigilanceAlarmId)
{
      TrackVigilanceAlarm_ptr m_tva = TrackVigilanceAlarm::create(TrackVigilanceAlarmId);
      m_tvawriter->dispose(m_tva);
}

Void  VigilatorLocal::deleteVigilanceAlarm(OID VigilanceAlarmId)
{
      VigilanceAlarm_ptr   m_va  = VigilanceAlarm::create(VigilanceAlarmId);
      m_vawriter->dispose(m_va);
}

Void  VigilatorLocal::deletingTopicsRelatedFigureTopics()
{
   cout << "deletingTopicsRelatedFigureTopics : " << endl;
   // tenemos dos tablas, la actual y la mas reciente
   // dos listas, una de figuras y otra de tracks q contienen los Id's de los topicos con estado dispose, se creo en la lectura

   // tracks
   list<string> lsTracksFromEarlierTable;                // <OIDTrk>
   list<string> lsTracksFromCurrentTable;                // <OIDTrk>

   list<pair<string, UInt> >::iterator it;               // <OIDFig, Tipo_Topic_Fig>
   list<string>::iterator  jt;                           // <OIDTrk>
   multimap<pair<string, string>, string>::iterator kt;  // <<OIDFig, OIDTrk>, OIDVigAlarm>
   for (it = m_DisposeFigureTopics.begin(); it != m_DisposeFigureTopics.end(); it++)
   {
      // lista de tracks de la tabla reciente
      lsTracksFromEarlierTable = getTrackListOfFigureTopicOfTable(*it, m_earlierVigilanceMap);
      // lista de tracks de la tabla actual
      lsTracksFromCurrentTable = getTrackListOfFigureTopicOfTable(*it, m_currentVigilanceMap);
      lsTracksFromCurrentTable.merge(lsTracksFromEarlierTable);
      lsTracksFromCurrentTable.unique();

      // delete TrackVigilanciaAlarm's
      for (jt = lsTracksFromCurrentTable.begin(); jt != lsTracksFromCurrentTable.end(); jt++)
      {
         pair<string, string> element;
         element.first  = (*it).first;
         element.second = (*jt);
         kt = m_earlierOIdsTrackVigAlarm.find(element);
         if (kt != m_earlierOIdsTrackVigAlarm.end())
         {
            // encontro el Id de TrackVigilanciaAlarm en m_earlierOIdsTrackVigAlarm
            deleteTrackVigilanceAlarm((*kt).second.c_str());
         }
         else if (kt != m_currentOIdsTrackVigAlarm.end())
         {
            // encontro el Id de TrackVigilanciaAlarm en m_currentOIdsTrackVigAlarm
            deleteTrackVigilanceAlarm((*kt).second.c_str());
         }
      }

      // delete VigilanciaAlarm
      deleteVigilanceAlarm((*it).first);
   }
}

Void  VigilatorLocal::deletingTopicsRelatedTrackTopics()
{
   cout << "m_earlierListOfFiguresFound.size : " << m_earlierListOfFiguresFound.size() << endl;
   cout << "m_DisposeTrackTopics.size        : " << m_DisposeTrackTopics.size() << endl;

   list<pair<string, UInt> >::iterator it;               // <OIDFig, Tipo_Topic_Fig>
   list<pair<string, UInt> >::iterator jt;               // <OIDTrk, Tipo_Topic_Trk>
   multimap<pair<string, string>, string>::iterator kt;  // <<OIDFig, OIDTrk>, OIDVigAlarm>
   multimap<string, string>::iterator  pt;               // <OIDFig, OIDTrk>
   for (it = m_earlierListOfFiguresFound.begin(); it != m_earlierListOfFiguresFound.end(); it++)
   {
      string IdFigure   = (*it).first;
      for (jt = m_DisposeTrackTopics.begin(); jt != m_DisposeTrackTopics.end(); jt++)
      {
         string IdTrack    = (*jt).first;
         cout << "IdFigure : " << IdFigure << ", IdTrack : " << IdTrack << endl;
         pair<string, string> key(IdFigure, IdTrack);
         kt = m_currentOIdsTrackVigAlarm.find(key);
         if (kt != m_currentOIdsTrackVigAlarm.end())
         {
            string IdTrackVigilanceAlarm = (*kt).second;
            deleteTrackVigilanceAlarm(IdTrackVigilanceAlarm);
         }
         else
         {
            // Si el par no es encontrado, el contacto no ha invadido el SS que conforma el par
         }

         // verificamos la existencia del topic padre
         list<string> trks = getTrackListOfFigureTopicOfTable((*it), m_earlierVigilanceMap);
         if (trks.size() == 1)
         {
            pt = m_earlierOIdsVigAlarm.find(IdFigure);
            if (pt != m_earlierOIdsVigAlarm.end())
            {
               // encontro el Id de VigilanciaAlarm en m_earlierOIdsVigAlarm
               string idVigilanceAlarm  = (*pt).second;
               deleteVigilanceAlarm(idVigilanceAlarm);
            }
         }
      }
   }
}

/* 3 */
Void  VigilatorLocal::detectionProcess()
{
   // barrido de las figuras circulares relativas
   if (!m_relativeCircularHash.empty())
   {
      // topicos figura circular
      HashMap<OID, RelativeCircularFigureKinematic_ptr>::Type::iterator i;
      for (i = m_relativeCircularHash.begin(); i != m_relativeCircularHash.end(); i++)
      {
         m_currentRelativeCircularSector  = (*i).second;
         navigationaid::FigureType  figureType = m_currentRelativeCircularSector->getFigureTypeValue();
         scFigureTopic  = SecuritySectorFigureTopic_RELATIVE_CIRCULAR_FIGURE;
         // tracks cercanos
         findSimTracksCloseToCircularFigure();
         if (!m_nearSimTrackHash.empty())
         {
            HashMap<OID, SimulatedTrackKinematic_ptr>::Type::iterator j;
            for (j = m_nearSimTrackHash.begin(); j != m_nearSimTrackHash.end(); j++)
            {
               m_currentSimulatedTrackKinematic = (*j).second;
               // Ejecutar el algoritmo de deteccion por tipo de figura
               findInvasionsToSecuritySectorToSimulatedTrack(figureType);
            }
         }
      }
   }

   // barrido de las figuras circulares fijas
   if (!m_fixedCircularHash.empty())
   {
      HashMap<OID, FixedCircularFigure_ptr>::Type::iterator i;
      for (i = m_fixedCircularHash.begin(); i != m_fixedCircularHash.end(); i++)
      {
         m_currentFixedCircularSector  = (*i).second;
         navigationaid::FigureType  figureType  = m_currentFixedCircularSector->getFigureTypeValue();
         scFigureTopic  = SecuritySectorFigureTopic_FIXED_CIRCULAR_FIGURE;
         // encontramos los tracks cercanos
         findSimTracksCloseToCircularFigure();
         if (!m_nearSimTrackHash.empty())
         {
            HashMap<OID, SimulatedTrackKinematic_ptr>::Type::iterator   j;
            for (j = m_nearSimTrackHash.begin(); j != m_nearSimTrackHash.end(); j++)
            {
               m_currentSimulatedTrackKinematic = (*j).second;
               // detección
               findInvasionsToSecuritySectorToSimulatedTrack(figureType);
            }
            // aqui termina de encontrar todas las parejas detectadas por Sector Circular
         }
      }
   }

   // barrido de las figuras poligonales relativas
   if (!m_relativePolylineHash.empty())
   {
      // topicos figura polyline
      HashMap<OID, RelativePolylineFigureKinematic_ptr>::Type::iterator i;
      for (i = m_relativePolylineHash.begin(); i != m_relativePolylineHash.end(); i++)
      {
         m_currentRelativePolylineSector  = (*i).second;
         navigationaid::FigureType  figureType = m_currentRelativePolylineSector->getFigureTypeValue();
         scFigureTopic  = SecuritySectorFigureTopic_RELATIVE_POLYLINE_FIGURE;
         // tracks cercanos?
         findSimTracksCloseToPolylineFigure();
         if (!m_nearSimTrackHash.empty())
         {
            HashMap<OID, SimulatedTrackKinematic_ptr>::Type::iterator j;
            for (j = m_nearSimTrackHash.begin(); j != m_nearSimTrackHash.end(); j++)
            {
               m_currentSimulatedTrackKinematic = (*j).second;
               // Ejecutar el algoritmo de deteccion por tipo de figura
               findInvasionsToSecuritySectorToSimulatedTrack(figureType);
            }
         }
      }
   }

   // barrido de las figuras poligonales fijas
   if (!m_fixedPolylineHash.empty())
   {
      // topicos figura polyline
      HashMap<OID, FixedPolylineFigure_ptr>::Type::iterator i;
      for (i = m_fixedPolylineHash.begin(); i != m_fixedPolylineHash.end(); i++)
      {
         m_currentFixedPolylineSector  = (*i).second;
         navigationaid::FigureType  figureType = m_currentFixedPolylineSector->getFigureTypeValue();
         scFigureTopic  = SecuritySectorFigureTopic_FIXED_POLYLINE_FIGURE;
         // tracks cercanos?
         findSimTracksCloseToPolylineFigure();
         if (!m_nearSimTrackHash.empty())
         {
            HashMap<OID, SimulatedTrackKinematic_ptr>::Type::iterator j;
            for (j = m_nearSimTrackHash.begin(); j != m_nearSimTrackHash.end(); j++)
            {
               m_currentSimulatedTrackKinematic = (*j).second;
               // Ejecutar el algoritmo de deteccion por tipo de figura
               findInvasionsToSecuritySectorToSimulatedTrack(figureType);
            }
         }
      }
   }
   // aqui se han encontrado todas las parejas posibles detectadas
   // las cuales son usadas para escribir los topicos de vigilancia
   // tambien para realizar dispose de topicos de vigilance

   // aqui, primero realizamos los dipose de los topicos relacionados a las figuras y los tracks relacionados a ellas
   deletingTopicsRelatedFigureTopics();

   // luego se realiza los dispose a los topicos de vigilancia relacionados a los tracks en estado dispose, por cada figura actual
   deletingTopicsRelatedTrackTopics();

   // backup de la ultima tabla procesada y de las listas de Figuras y Tracks
   makeEarlierDataVigilance();
}

Void  VigilatorLocal::makeEarlierDataVigilance()
{
   // se limpian las tablas mas recientes antes de guardar la tabla actual
   m_earlierListOfFiguresFound.clear();
   m_earlierListOfTracksFound.clear();
   // creacion de las listas recientes desde la tabla actual
   multimap<pair<string, UInt>, pair<string, UInt> >::iterator  it;
   for (it = m_currentVigilanceMap.begin(); it != m_currentVigilanceMap.end(); it++)
   {
//      cout << "(*it).first.first : " << (*it).first.first << endl;
//      cout << "(*it).second.first : " << (*it).second.first << endl;
      m_earlierListOfFiguresFound.push_back((*it).first);
      m_earlierListOfTracksFound.push_back((*it).second);
   }
   m_earlierListOfFiguresFound.unique();
   m_earlierListOfTracksFound.unique();

   // Tabla <IdFig, IdTrk>
   m_earlierVigilanceMap.clear();
   m_earlierVigilanceMap   = m_currentVigilanceMap;   
   // Topicos VigilanceAlarm
   m_earlierOIdsVigAlarm.clear();
   m_earlierOIdsVigAlarm   = m_currentOIdsVigAlarm;
   // Topicos TrackVigilanceAlarm
   m_earlierOIdsTrackVigAlarm.clear();
   m_earlierOIdsTrackVigAlarm = m_currentOIdsTrackVigAlarm;

   //   cout << "m_earlierVigilanceMap.size : " << m_earlierVigilanceMap.size() << endl;
}

Bool  VigilatorLocal::isThereTrackOId(pair<string, UInt> TrackOId)
{
   list<pair<string, UInt> >::iterator  it;
   it = std::find(m_earlierListOfTracksFound.begin(), m_earlierListOfTracksFound.end(), TrackOId);
   Bool bRetorna = False;
   if (it != m_earlierListOfTracksFound.end())
      bRetorna = True;
   return   bRetorna;
}

list<string>   VigilatorLocal::getTrackListOfFigureTopicOfTable(pair<string, UInt> FigureTopic, multimap<pair<string, UInt>, pair<string, UInt> > Tabla)
{
   list<string>   retorna;
   multimap<pair<string, UInt>, pair<string, UInt> >::iterator   it;
   pair<multimap<pair<string, UInt>, pair<string, UInt> >::iterator, multimap<pair<string, UInt>, pair<string, UInt> >::iterator> ret;
   ret = Tabla.equal_range(FigureTopic);
   for (it=ret.first; it!=ret.second; ++it){
      cout << " " << (*it).second.first << endl;
      retorna.push_back((*it).second.first);
   }
   return retorna;
}

/* 4 */
Void  VigilatorLocal::findSimTracksCloseToCircularFigure()
{
   if (m_allSimTrackHash.empty())  return;

   Bool  bNear;
   HashMap<OID, SimulatedTrackKinematic_ptr>::Type::iterator it;
   for (it = m_allSimTrackHash.begin(); it != m_allSimTrackHash.end(); it++)
   {
      // incluir el timer para filtrar por periodo de cada track, se encuentra en SimulatedTrack
      bNear = False;
      newCoordinatesResult newCoordinates;
      if (scFigureTopic == SecuritySectorFigureTopic_RELATIVE_CIRCULAR_FIGURE)
      {
         newCoordinates = detectionAlgorithm.generateNewBoundaryCoordinates(m_currentRelativeCircularSector->getMaxLatitude(),
                                                                            m_currentRelativeCircularSector->getMaxLongitude(),
                                                                            m_currentRelativeCircularSector->getMinLatitude(),
                                                                            m_currentRelativeCircularSector->getMinLongitude(),
                                                                            fr);
      }
      else if (scFigureTopic == SecuritySectorFigureTopic_FIXED_CIRCULAR_FIGURE)
      {
         newCoordinates = detectionAlgorithm.generateNewBoundaryCoordinates(m_currentFixedCircularSector->getMaxLatitude(),
                                                                            m_currentFixedCircularSector->getMaxLongitude(),
                                                                            m_currentFixedCircularSector->getMinLatitude(),
                                                                            m_currentFixedCircularSector->getMinLongitude(),
                                                                            fr);
      }

      Float lon = (*it).second->getCurrentLongitude();
      Float lat = (*it).second->getCurrentLatitude();
      Float minLat, maxLat, minLon, maxLon;

      maxLat   = newCoordinates.newMaxLat;
      maxLon   = newCoordinates.newMaxLon;
      minLat   = newCoordinates.newMinLat;
      minLon   = newCoordinates.newMinLon;

      bNear =  (minLon <= lon) && (lon <= maxLon) && (minLat <= lat) && (lat <= maxLat);
      // test
      cout << "CIRCULAR :  Latitud  ["                   << minLat << " <= " << lat << " <= " << maxLat << "]" << endl;
      cout << "bNear : " << bNear   << "   Longitud ["   << minLon << " <= " << lon << " <= " << maxLon << "]" << endl;

      if (bNear)
      {
         // escribir en m_nearSimTrackHash, solo se esta considerando tracks simulados
         m_nearSimTrackHash[(*it).second->getSimulatedTrackId()]  = (*it).second;
      }
   }

   ///////////////////////////////////////
   // test
   cout << "|---------------------------------------------------------------------------" << endl;
   for (it = m_nearSimTrackHash.begin(); it != m_nearSimTrackHash.end(); it++)
   {
//      cout << "first : " << (*it).first << endl;
      cout << "m_nearSimTrackHash : " << (*it).second->getName() << endl;
   }
   cout << "---------------------------------------------------------------------------|" << endl;
   ///////////////////////////////////////

}

/* 5 */
Void  VigilatorLocal::findSimTracksCloseToPolylineFigure()
{
   // incluir el timer para filtrar por periodo de cada track, se encuentra en SimulatedTrack
   if (m_allSimTrackHash.empty())  return;
   Bool  bNear;
   HashMap<OID, SimulatedTrackKinematic_ptr>::Type::iterator it;
   for (it = m_allSimTrackHash.begin(); it != m_allSimTrackHash.end(); it++)
   {
      bNear = False;
      newCoordinatesResult newCoordinates;
      if (scFigureTopic == SecuritySectorFigureTopic_RELATIVE_POLYLINE_FIGURE)
      {
         newCoordinates = detectionAlgorithm.generateNewBoundaryCoordinates(m_currentRelativePolylineSector->getMaxLatitude(),
                                                                            m_currentRelativePolylineSector->getMaxLongitude(),
                                                                            m_currentRelativePolylineSector->getMinLatitude(),
                                                                            m_currentRelativePolylineSector->getMinLongitude(),
                                                                            fr);
      }
      else if (scFigureTopic == SecuritySectorFigureTopic_FIXED_POLYLINE_FIGURE)
      {
         newCoordinates = detectionAlgorithm.generateNewBoundaryCoordinates(m_currentFixedPolylineSector->getMaxLatitude(),
                                                                            m_currentFixedPolylineSector->getMaxLongitude(),
                                                                            m_currentFixedPolylineSector->getMinLatitude(),
                                                                            m_currentFixedPolylineSector->getMinLongitude(),
                                                                            fr);
      }

      Float lon = (*it).second->getCurrentLongitude();
      Float lat = (*it).second->getCurrentLatitude();
      Float minLat, maxLat, minLon, maxLon;

      maxLat   = newCoordinates.newMaxLat;
      maxLon   = newCoordinates.newMaxLon;
      minLat   = newCoordinates.newMinLat;
      minLon   = newCoordinates.newMinLon;

      bNear =  (minLon <= lon) && (lon <= maxLon) && (minLat <= lat) && (lat <= maxLat);

      // test
      cout << "POLIGONO :  Latitud  ["                   << minLat << " <= " << lat << " <= " << maxLat << "]" << endl;
      cout << "bNear : " << bNear   << "   Longitud ["   << minLon << " <= " << lon << " <= " << maxLon << "]" << endl;

      if (bNear)
      {
         // escribir en m_nearSimTrackHash
         m_nearSimTrackHash[(*it).second->getSimulatedTrackId()]  = (*it).second;
      }
   }
}

/* 6 */
Void  VigilatorLocal::findInvasionsToSecuritySectorToSimulatedTrack(navigationaid::FigureType  figureType)
{
   string   sFig  = ""; // OID del topico Figura, no considera el tipo de topico
   string   sTrk  = ""; // OID del topico Track, no considera el tipo de topico
   // Resultado del algoritmo de deteccion
   Bool  bDetected   = False;
   // Tipo de figura: Circulo, Sector circular & Sector de anillo? y Track simulado
   Bool  bFigureType = False;

//   cout << "scFigureTopic : " << scFigureTopic << endl;
   bFigureType =  (figureType == navigationaid::FigureType_CIRCLE)         ||
                  (figureType == navigationaid::FigureType_CIRCULARSECTOR) ||
                  (figureType == navigationaid::FigureType_RINGSECTOR);

   map<string, string>::iterator                 it;
   map<pair<string, string>, string>::iterator   jt;
   OID      idTrackVigilanceAlarm("");
   OID      idVigilanceAlarm("");

   if (bFigureType)
   {
      Float MinRadio = 0;
      if (scFigureTopic == SecuritySectorFigureTopic_RELATIVE_CIRCULAR_FIGURE)
      {
         // Necesario para el pintado del circulo en GUI
         if (figureType != navigationaid::FigureType_CIRCLE)
            MinRadio = m_currentRelativeCircularSector->getMinRadio();

         bDetected   = detectionAlgorithm.verifyTrackInsideRingSector(m_currentRelativeCircularSector->getCenterLatitude(),
                                                                      m_currentRelativeCircularSector->getCenterLongitude(),
                                                                      m_currentRelativeCircularSector->getInitialAngle(),
                                                                      m_currentRelativeCircularSector->getSpanAngle(),
                                                                      MinRadio,
                                                                      m_currentRelativeCircularSector->getMaxRadio(),
                                                                      m_currentSimulatedTrackKinematic->getCurrentLatitude(),
                                                                      m_currentSimulatedTrackKinematic->getCurrentLongitude());

         sFig     = m_currentRelativeCircularSector->getRelativeCircularFigureId().c_str();
         sTrk     = m_currentSimulatedTrackKinematic->getSimulatedTrackId().c_str();
      }
      else if (scFigureTopic == SecuritySectorFigureTopic_FIXED_CIRCULAR_FIGURE)
      {
         // Necesario para el pintado del circulo en GUI
         if (figureType != navigationaid::FigureType_CIRCLE)
            MinRadio = m_currentFixedCircularSector->getMinRadio();

         bDetected   = detectionAlgorithm.verifyTrackInsideRingSector(m_currentFixedCircularSector->getCenterLatitude(),
                                                                      m_currentFixedCircularSector->getCenterLongitude(),
                                                                      m_currentFixedCircularSector->getInitialAngle(),
                                                                      m_currentFixedCircularSector->getSpanAngle(),
                                                                      MinRadio,
                                                                      m_currentFixedCircularSector->getMaxRadio(),
                                                                      m_currentSimulatedTrackKinematic->getCurrentLatitude(),
                                                                      m_currentSimulatedTrackKinematic->getCurrentLongitude());

         sFig     = m_currentFixedCircularSector->getFixedCircularFigureId().c_str();
         sTrk     = m_currentSimulatedTrackKinematic->getSimulatedTrackId().c_str();
      }

      pair<string, UInt> one(sFig, scFigureTopic);                // key   (Figura)
      pair<string, UInt> two(sTrk, TrackTopic_SIMULATED_TRACK);   // value (Track)

      cout << "CIRCULAR :  bDetected   : " << bDetected  << endl;
      if (bDetected)
      {
//         cout << "insertado : " << "one.first : " << one.first << " - two.first : " << two.first << endl;
         // aqui se insertan las parejas detectadas
         m_currentVigilanceMap.insert(pair<pair<string, UInt>, pair<string, UInt> >(one, two));

         // Generacion del OID para el topico VigilanciaAlarm, relacionado a la figura actual procesada
         // busco en la tabla mas reciente
         it = m_earlierOIdsVigAlarm.find(sFig);
         if (it != m_earlierOIdsVigAlarm.end())
         {
            // si lo encuentra, obtengo el Id de VigilanceAlarm
            idVigilanceAlarm = (*it).second;
//            cout << "idVigilanceAlarm -if : " << idVigilanceAlarm.c_str() << endl;
         }
         else
         {
            // si no lo encuentra, lo genero, y guardo el nuevo Id en la tabla actual
            idVigilanceAlarm  = generateUuid();
//            cout << "idVigilanceAlarm -el 1 : " << idVigilanceAlarm.c_str() << endl;
            string   sVig  = idVigilanceAlarm.c_str();
            m_currentOIdsVigAlarm.insert(pair<string, string>(sFig, sVig));
         }
         // aqui el OID VigilanceAlarm ya esta insertado en la tabla m_currentOIdsVigAlarm

         // Escritura del topico VigilanceAlarm
         VigilanceAlarm_ptr   vigilanceAlarm;
         vigilanceAlarm   = VigilanceAlarm::create(idVigilanceAlarm,
                                                   getCurrentTime(),
                                                   "000",
                                                   1,
                                                   sFig.c_str(),
                                                   SecuritySectorFigureTopic_RELATIVE_CIRCULAR_FIGURE,
                                                   m_nodeConfigurate);

         m_vawriter->write(vigilanceAlarm);

         // Generacion del OID para el topico TrackVigilanciaAlarm, relacionado a la figura y el track actual
         // buscar el OID TrackVigilanceAlarm
         pair<string, string> key(sFig, sTrk);
         jt = m_earlierOIdsTrackVigAlarm.find(key);
         if (jt != m_earlierOIdsTrackVigAlarm.end())
         {
            idTrackVigilanceAlarm   = (*jt).second;
         }
         else
         {
            idTrackVigilanceAlarm   = generateUuid();
//            cout << "idTrackVigilanceAlarm -el 1 : " << idTrackVigilanceAlarm.c_str() << endl;
            string   sVigTrk  = idTrackVigilanceAlarm.c_str();
            m_currentOIdsTrackVigAlarm.insert(pair<pair<string, string>, string>(pair<string, string>(sFig, sTrk), sVigTrk));
         }

         // Escritura del topico TrackVigilanceAlarm
         TrackVigilanceAlarm_ptr trackVigilanceAlarm;
         trackVigilanceAlarm  = TrackVigilanceAlarm::create(idTrackVigilanceAlarm,
                                                            idVigilanceAlarm,
                                                            (OID)sTrk,
                                                            TrackTopic_SIMULATED_TRACK);
         m_tvawriter->write(trackVigilanceAlarm);
      }
      else
      {
         // el algoritmo, no detecto el track en el SS, pero el track estuvo en la zona de seguridad?
         Bool bWasItDeteceted = isThereTrackOId(two);
         cout << "detectado, pero salio del SS: " << bWasItDeteceted << endl;
         if (bWasItDeteceted)
         {
            // buscar el OID TrackVigilanceAlarm
            pair<string, string> key(sFig, sTrk);
            jt = m_earlierOIdsTrackVigAlarm.find(key);
            if (jt != m_earlierOIdsTrackVigAlarm.end())
            {
               idTrackVigilanceAlarm   = (*jt).second;
               deleteTrackVigilanceAlarm(idTrackVigilanceAlarm);
            }
            // el track que ya no esta en el SS pero que fue detectado anteriormente
            // es el unico track o hay mas tracks relacionados al SS?
            // si en la lista reciente de tracks detectados relacionados a la figura actual, solo existe este track
            // entonces, no hay topicos TrackVigilanceAlarm, acabamos de elminar el ultimo
            // debe pasarse al estado dispose el topico VigilanceAlarm relacionado al SS

            // verificamos la existencia del topic padre
            pair<string, UInt>   keyFigureTopic(sFig, scFigureTopic);
            list<string> trks = getTrackListOfFigureTopicOfTable(keyFigureTopic, m_earlierVigilanceMap);
            if (trks.size() == 1)
            {
               it = m_earlierOIdsVigAlarm.find(sFig);
               if (it != m_earlierOIdsVigAlarm.end())
               {
                  // encontro el Id de VigilanciaAlarm en m_earlierOIdsVigAlarm
                  idVigilanceAlarm  = (*it).second;
                  deleteVigilanceAlarm(idVigilanceAlarm);
               }
            }

         }
      }
      return;
   }

   // Poligono & Rectangulo con Track simulado
   bFigureType =  (figureType == navigationaid::FigureType_POLYGON)  ||
                  (figureType == navigationaid::FigureType_RECTANGLE);

   if  (bFigureType)
   {
      if (scFigureTopic == SecuritySectorFigureTopic_RELATIVE_POLYLINE_FIGURE)
      {
         bDetected   = detectionAlgorithm.verifyTrackInsidePolygon(m_currentRelativePolylineSector->getPointsLatitudes(),
                                                                   m_currentRelativePolylineSector->getPointsLongitudes(),
                                                                   m_currentSimulatedTrackKinematic->getCurrentLatitude(),
                                                                   m_currentSimulatedTrackKinematic->getCurrentLongitude());

         sFig     = m_currentRelativePolylineSector->getRelativePolylineFigureId().c_str();
         sTrk     = m_currentSimulatedTrackKinematic->getSimulatedTrackId().c_str();
      }
      else if (scFigureTopic == SecuritySectorFigureTopic_FIXED_POLYLINE_FIGURE)
      {
         bDetected   = detectionAlgorithm.verifyTrackInsidePolygon(m_currentFixedPolylineSector->getPointsLatitudes(),
                                                                   m_currentFixedPolylineSector->getPointsLongitudes(),
                                                                   m_currentSimulatedTrackKinematic->getCurrentLatitude(),
                                                                   m_currentSimulatedTrackKinematic->getCurrentLongitude());

         sFig     = m_currentFixedPolylineSector->getFixedPolylineFigureId().c_str();
         sTrk     = m_currentSimulatedTrackKinematic->getSimulatedTrackId().c_str();
      }

      pair<string, UInt> one(sFig, scFigureTopic);                // key   (Figura)
      pair<string, UInt> two(sTrk, TrackTopic_SIMULATED_TRACK);   // value (Track)

      cout << "POLIGONO :  bDetected   : " << bDetected  << endl;
      if (bDetected)
      {
//         cout << "one.first : " << one.first << " - two.first : " << two.first << endl;
         // aqui se insertan las parejas detectadas
         m_currentVigilanceMap.insert(pair<pair<string, UInt>, pair<string, UInt> >(one, two));

         // Generacion del OID para el topico VigilanciaAlarm, relacionado a la figura actual procesada
         // busco en la tabla mas reciente
         it = m_earlierOIdsVigAlarm.find(sFig);
         if (it != m_earlierOIdsVigAlarm.end())
         {
            // si lo encuentra, obtengo el Id de VigilanceAlarm
            idVigilanceAlarm = (*it).second;
//            cout << "idVigilanceAlarm -if : " << idVigilanceAlarm.c_str() << endl;
         }
         else
         {
            // si no lo encuentra, lo genero y guardo el nuevo Id en la tabla actual
            idVigilanceAlarm  = generateUuid();
            string   sVig  = idVigilanceAlarm.c_str();
            m_currentOIdsVigAlarm.insert(pair<string, string>(sFig, sVig));
         }
         // aqui el OID VigilanceAlarm ya esta insertado en la tabla m_currentOIdsVigAlarm

         // Escritura del topico VigilanceAlarm
         VigilanceAlarm_ptr   vigilanceAlarm;
         vigilanceAlarm   = VigilanceAlarm::create(idVigilanceAlarm,
                                                   getCurrentTime(),
                                                   "000",
                                                   1,
                                                   sFig.c_str(),
                                                   SecuritySectorFigureTopic_RELATIVE_POLYLINE_FIGURE,
                                                   m_nodeConfigurate);

         m_vawriter->write(vigilanceAlarm);

         // Generacion del OID para el topico TrackVigilanciaAlarm, relacionado a la figura y el track actual
         // buscar el OID TrackVigilanceAlarm
         pair<string, string> key(sFig, sTrk);
         jt = m_earlierOIdsTrackVigAlarm.find(key);
         if (jt != m_earlierOIdsTrackVigAlarm.end())
         {
            idTrackVigilanceAlarm   = (*jt).second;
         }
         else
         {
            idTrackVigilanceAlarm   = generateUuid();
            string   sVigTrk  = idTrackVigilanceAlarm.c_str();
            m_currentOIdsTrackVigAlarm.insert(pair<pair<string, string>, string>(pair<string, string>(sFig, sTrk), sVigTrk));
         }

         // Escritura del topico VigilanceAlarm
         TrackVigilanceAlarm_ptr trackVigilanceAlarm;
         trackVigilanceAlarm  = TrackVigilanceAlarm::create(idTrackVigilanceAlarm,
                                                            idVigilanceAlarm,
                                                            (OID)sTrk,
                                                            TrackTopic_SIMULATED_TRACK);
         m_tvawriter->write(trackVigilanceAlarm);
      }
      else
      {
         // el algoritmo, no detecto el track en el SS, pero el track estuvo en la zona de seguridad?
         Bool bWasItDeteceted = isThereTrackOId(two);
         cout << "detectado, pero salio del SS: " << bWasItDeteceted << endl;
         if (bWasItDeteceted)
         {
            // buscar el OID TrackVigilanceAlarm
            pair<string, string> key(sFig, sTrk);
            jt = m_earlierOIdsTrackVigAlarm.find(key);
            if (jt != m_earlierOIdsTrackVigAlarm.end())
            {
               idTrackVigilanceAlarm   = (*jt).second;
               deleteTrackVigilanceAlarm(idTrackVigilanceAlarm);
            }
            // el track que ya no esta en el SS pero que fue detectado anteriormente
            // es el unico track o hay mas tracks relacionados al SS?
            // si en la lista reciente de tracks detectados relacionados a la figura actual, solo existe este track
            // entonces, no hay topicos TrackVigilanceAlarm, acabamos de elminar el ultimo
            // debe pasarse al estado dispose el topico VigilanceAlarm relacionado al SS

            pair<string, UInt>   keyFigureTopic(sFig, scFigureTopic);
            list<string> trks = getTrackListOfFigureTopicOfTable(keyFigureTopic, m_earlierVigilanceMap);
            if (trks.size() == 1)
            {
               it = m_earlierOIdsVigAlarm.find(sFig);
               if (it != m_earlierOIdsVigAlarm.end())
               {
                  // encontro el Id de VigilanciaAlarm en m_earlierOIdsVigAlarm
                  idVigilanceAlarm  = (*it).second;
                  deleteVigilanceAlarm(idVigilanceAlarm);
               }
            }

         }
      }
      return;
   }

}

Timestamp   VigilatorLocal::getCurrentTime()
{
   timespec    timeSystem;
   clock_gettime(CLOCK_REALTIME, &timeSystem);  ///< Obteniendo la hora actual
   Timestamp   currentTime;
   currentTime.sec      = timeSystem.tv_sec;
   currentTime.nanosec  = timeSystem.tv_nsec;
   return   currentTime;
}

/* 2.1 */
Bool  VigilatorLocal::isDisposedState(ddswrapper::DataInfo di)
{
   Bool  takeTopic   = False;
   switch(di.getInstanceState())
   {
   case  ddswrapper::InstanceStateNew: case  ddswrapper::InstanceStateUpdated: case  ddswrapper::InstanceStateNoWriters:
      takeTopic   = False;
      break;
   case  ddswrapper::InstanceStateDisposed:
      takeTopic   = True;
      break;
   }
   return takeTopic;
}

/* 2.2 */
Bool  VigilatorLocal::isTimeIntervalValid(SimulatedTrack_ptr entity)
{
   //            Timestamp timeStart;
   /*Int32 */timeNowInSeconds = 0;
   Int32 timeFutureInSeconds = 0;

   timespec timeSystem;
   clock_gettime(CLOCK_REALTIME, &timeSystem);  ///< Obteniendo la hora actual
   timeStart.sec     = timeSystem.tv_sec;
   timeNowInSeconds  = timeStart.sec;           // tiempo actual del sistema

   m_trackId      = entity->getSimulatedTrackId();
   m_timeUpdate   = entity->getTimeUpdatePeriod(); ///< obteniendo periodo de actualizacion del contacto, 2 o 3 seg.

   if (m_frequency.find(m_trackId) != m_frequency.end())
   {
      timeFutureInSeconds    = m_frequency[m_trackId]; ///< Obteniendo el tiempo en segundos del vector de ayuda
   }
   else
   {
      m_frequency[m_trackId] = timeNowInSeconds; ///< Insertando tiempo en segundos en el vector de ayuda
      timeFutureInSeconds    = timeNowInSeconds;
   }

   ///< Calculando el tiempo valido para simular el contacto
   Bool doCalculate = false;
   if ((timeNowInSeconds == timeFutureInSeconds) || (timeNowInSeconds > (timeFutureInSeconds + (int) m_timeUpdate)))
   {
      doCalculate = true;
   }
   return doCalculate;
}

/* 2.3 */
Bool  VigilatorLocal::writeSimulatedTrackKinematic(SimulatedTrack_ptr entity)
{
   Float64     m_timeElapsed  = 0;
   Float64     m_speed        = entity->getSpeed();
   Timestamp   m_dateTrack    = entity->getDateCreation();

   if (entity->getDateCreation().stamp != entity->getDateUpdate().stamp)
   {
      m_dateTrack = entity->getDateUpdate(); ///< Si se ha actualizado el track entonces se toma el campo dateUpdate, como tiempo para calcular el movimiento
   }

   m_kinematics->setLatLon(entity->getLatitude(), entity->getLongitude());
   m_timeElapsed  = (timeStart.sec - m_dateTrack.sec);
   m_distance     = (m_speed * m_timeElapsed);
   m_kinematics->move(entity->getCourse(), m_distance / 1852);

   SimulatedTrackKinematic_ptr track = SimulatedTrackKinematic::create(
            m_trackId,
            m_nodeId,
            entity->getOwnerId(),
            m_speed,
            entity->getCourse(),
            m_kinematics->getLatitude(),
            m_kinematics->getLongitude(),
            m_distance,
            entity->getSimulatedTrackClass(),
            entity->getSimulatedTrackClassification(),
            entity->getSimulatedTrackType(),
            entity->getName());

   Bool  retorna = m_stk_writer->write(track);
   cout << "Track:" << entity->getName().c_str() /*<< m_trackId.c_str() */<< " lat: " << m_kinematics->getLatitude() << " lon: " << m_kinematics->getLongitude() << " Dis:" << m_distance << " cur:" << entity->getCourse() << endl;
   //            cout << "m_trackId = " << m_trackId << "\n" << "m_nodeId = " << m_nodeId << "\n" << "entity->getOwnerId() = " << entity->getOwnerId() << endl;
   return   retorna;
}

/* 2 */
Void  VigilatorLocal::processingTrack(ddswrapper::DataInfo di, SimulatedTrack_ptr entity)
{
   if (!(di.isValidData() && !isDisposedState(di)))
   {
      return;
   }
   m_nodeId = entity->getNodeId();   // obtiene el nodo desde el cual proviene el topic.
   if (m_nodeConfigurate != m_nodeId)
   {
      return;
   }
   if (!isTimeIntervalValid(entity))
   {
      return;
   }
   if (!writeSimulatedTrackKinematic(entity))
   {
      return;
   }
   if (m_frequency.find(m_trackId) == m_frequency.end())
   {
      return;
   }
   m_frequency[m_trackId] = timeNowInSeconds; ///< Actualizando el tiempo en la colecccion
}

VigilatorLocal_ptr   VigilatorLocal::create()
{
   return VigilatorLocal_ptr(new VigilatorLocal());
}

VigilatorLocal::~VigilatorLocal()
{
   SimulatedTrackComm::instance().finalize();
}

Void  VigilatorLocal::setNodoId(OID nodoId)
{
   // asignado desde el run-local
   m_nodeConfigurate = nodoId;
}

/* 0 */
Void  VigilatorLocal::runVigilance()
{
   cout << "-------------------------------------------------------------------------------------" << endl;

   // 1. leer con periodo t, el topico SimulatedTrackReferenceSecuritySectorCollection
   // 2. si hay un topico del tipo anterior, actualizarlo y comenzar a leer tracks del ambito
   // 3. filtrar los topicos tracks por proximidad
   // 4. por cada topico filtrado calcular si se ha invadido el sector de seguridad

   m_running   =  True;
   // kinematic
   m_kinematics   = GeoCoordinate_ptr(new GeoCoordinate());

   // Inicializar SimulatedTrack Read
   SimulatedTrackComm::instance().initialize();
   SimulatedTrackComm::instance().enableReadPartition();
   m_streader     = SimulatedTrackComm::instance().getReader("GlobalVarayoc", "DefaultEntity", False);

   // Inicializar RelativeCircularFigureKinematic Read
   RelativeCircularFigureKinematicComm::instance().initialize();
   RelativeCircularFigureKinematicComm::instance().enableReadPartition();
   m_rcfkreader   = RelativeCircularFigureKinematicComm::instance().getReader("GlobalVarayoc", "DefaultEntity", False);

   // Inicializar FixedCircularFigure Read
   FixedCircularFigureComm::instance().initialize();
   FixedCircularFigureComm::instance().enableReadPartition();
   m_fcfreader    = FixedCircularFigureComm::instance().getReader("GlobalVarayoc", "DefaultEntity", False);

   // Inicializar FixedCircularFigure Write
   FixedCircularFigureComm::instance().enableWritePartition();
   m_fcfwriter   = FixedCircularFigureComm::instance().getWriter();

   // Inicializar RelativePolylineFigureKinematic Read
   RelativePolylineFigureKinematicComm::instance().initialize();
   RelativePolylineFigureKinematicComm::instance().enableReadPartition();
   m_rpfkreader   = RelativePolylineFigureKinematicComm::instance().getReader("GlobalVarayoc", "DefaultEntity", False);

   // Inicializar FixedPolylineFigure Read
   FixedPolylineFigureComm::instance().initialize();
   FixedPolylineFigureComm::instance().enableReadPartition();
   m_fpfreader   = FixedPolylineFigureComm::instance().getReader("GlobalVarayoc", "DefaultEntity", False);

   // Inicializar FixedPolylineFigureComm write
//   FixedPolylineFigureComm::instance().initialize();
   FixedPolylineFigureComm::instance().enableWritePartition();
   m_fpfwriter = FixedPolylineFigureComm::instance().getWriter();

   // Inicializar VigilanceAlarm Write
   VigilanceAlarmComm::instance().initialize();
   VigilanceAlarmComm::instance().enableWritePartition();
   m_vawriter     = VigilanceAlarmComm::instance().getWriter();

   // Inicializar VigilanceAlarm Read
//   VigilanceAlarmComm::instance().initialize();
   VigilanceAlarmComm::instance().enableReadPartition();
   m_vareader     = VigilanceAlarmComm::instance().getReader("GlobalVarayoc", "DefaultEntity", False);

   // Inicializar TrackVigilanceAlarm Write
   TrackVigilanceAlarmComm::instance().initialize();
   TrackVigilanceAlarmComm::instance().enableWritePartition();
   m_tvawriter     = TrackVigilanceAlarmComm::instance().getWriter();

   // Inicializar TrackVigilanceAlarm Read
//   TrackVigilanceAlarmComm::instance().initialize();
   TrackVigilanceAlarmComm::instance().enableReadPartition();
   m_tvareader     = TrackVigilanceAlarmComm::instance().getReader("GlobalVarayoc", "DefaultEntity", False);

   // es necesario inicializar dos veces? tanto para el read como para el write?
   // Inicializar SimulatedTrackKinematic Read
   SimulatedTrackKinematicComm::instance().initialize();
   SimulatedTrackKinematicComm::instance().enableReadPartition();
   m_stk_reader   = SimulatedTrackKinematicComm::instance().getReader("GlobalVarayoc", "DefaultEntity", False);

   // Inicializar SimulatedTrackKinematic Write
   SimulatedTrackKinematicComm::instance().initialize();
   SimulatedTrackKinematicComm::instance().enableWritePartition();
   m_stk_writer   = SimulatedTrackKinematicComm::instance().getWriter();

   // Timers
   m_verify_class_aereo->setInterval(4000);
   m_verify_class_aereo->startTimer();
   m_verify_class_super->setInterval(10000);
   m_verify_class_super->startTimer();

   while(m_running)
   {
      cout << endl << endl << "INICIO LOOP VIGILANCIA" << endl;
      initialize();
      // periodo de lectura del topico SimulatedTrackReferenceSecuritySectorCollection
      Int t = 1;
      sleep(t);
      // ejecucion interna de simulacion
      //readCollectionTrack();
      // para ver los topicos de vigilancia
      readSecuritySectorCollection();

      /*
               if (m_verify_class_aereo->checkTimer())
               {
                  cout << "check aereo" << endl;
                  m_ClassAereo   = True;
                  m_verify_class_aereo->startTimer();
               }
               if (m_verify_class_super->checkTimer())
               {
                  cout << "check super" << endl;
                  m_ClassSuper   = True;
                  m_verify_class_super->startTimer();
               }
*/

      // Vigilancia
      // primero se leen los sectores de seguridad SS
      readFilteredFigureCollection();
      // si hay SS se leen los tracks que usaran datos por cada sector de seguridad
      readFilteredTrackCollection();
      // Proceso de vigilancia
      detectionProcess();
   }

   // reset
   m_kinematics.reset();
   m_currentRelativeCircularSector.reset();
   m_currentFixedCircularSector.reset();
   m_currentRelativePolylineSector.reset();
   m_currentSimulatedTrackKinematic.reset();

   m_vawriter.reset();
   m_vareader.reset();
   m_tvawriter.reset();
   m_tvareader.reset();
   m_streader.reset();
   m_rcfkreader.reset();
   m_fcfreader.reset();
   m_rpfkreader.reset();
   m_fpfreader.reset();
   m_stk_writer.reset();
   m_stk_reader.reset();

   m_fcfwriter.reset();
   m_fpfwriter.reset();
   // finalize
   SimulatedTrackComm::instance().finalize();

   RelativeCircularFigureKinematicComm::instance().finalize();
   FixedCircularFigureComm::instance().finalize();
   RelativePolylineFigureKinematicComm::instance().finalize();
   FixedPolylineFigureComm::instance().finalize();
   VigilanceAlarmComm::instance().finalize();
   TrackVigilanceAlarmComm::instance().finalize();
   SimulatedTrackKinematicComm::instance().finalize();

}

Void     VigilatorLocal::runTester()
{
   // Inicializar TrackVigilanceAlarm Write
   TrackVigilanceAlarmComm::instance().initialize();
   TrackVigilanceAlarmComm::instance().enableWritePartition();
   m_tvawriter     = TrackVigilanceAlarmComm::instance().getWriter();

   // Inicializar TrackVigilanceAlarm Read
//   TrackVigilanceAlarmComm::instance().initialize();
   TrackVigilanceAlarmComm::instance().enableReadPartition();
   m_tvareader     = TrackVigilanceAlarmComm::instance().getReader("GlobalVarayoc", "DefaultEntity", False);

   // Inicializar VigilanceAlarm Write
   VigilanceAlarmComm::instance().initialize();
   VigilanceAlarmComm::instance().enableWritePartition();
   m_vawriter     = VigilanceAlarmComm::instance().getWriter();

   // Inicializar VigilanceAlarm Read
//   VigilanceAlarmComm::instance().initialize();
   VigilanceAlarmComm::instance().enableReadPartition();
   m_vareader     = VigilanceAlarmComm::instance().getReader("GlobalVarayoc", "DefaultEntity", False);

   cout << "m_nodeConfigurate : " << m_nodeConfigurate.c_str() << endl;
   // eliminar topics TrackVigilanceAlarm
   TrackVigilanceAlarmCollection    entitiesTVA;
   ddswrapper::DataInfoCollection   topicDataInfoCollectionTVA;
   m_tvareader->read(topicDataInfoCollectionTVA, entitiesTVA);
   for (UInt i = 0; i < entitiesTVA.size(); i++)
   {
      TrackVigilanceAlarm_ptr c = entitiesTVA[i];
      cout << "getTrackVigilanceAlarmID: " << c->getTrackVigilanceAlarmID().c_str() << endl;
      deleteTrackVigilanceAlarm(c->getTrackVigilanceAlarmID());
   }

   VigilanceAlarmCollection         entitiesVA;
   ddswrapper::DataInfoCollection   topicDataInfoCollectionVA;
   m_vareader->read(topicDataInfoCollectionVA, entitiesVA);
   for (UInt i = 0; i < entitiesVA.size(); i++)
   {
      VigilanceAlarm_ptr      c = entitiesVA[i];
      cout << "getVigilanceAlarmID     : " << c->getVigilanceAlarmID().c_str() << endl;
      deleteVigilanceAlarm(c->getVigilanceAlarmID());
   }

   m_vawriter.reset();
   m_vareader.reset();
   m_tvawriter.reset();
   m_tvareader.reset();

   TrackVigilanceAlarmComm::instance().finalize();
   VigilanceAlarmComm::instance().finalize();
}

}
}
}

